1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*!
Contexts for hash-consing terms
*/

use super::*;

/// A type which may be used as a context for creating `isotope` terms
pub trait ConsCtx {
    /// Whether when two terms are consed by this context they are guaranteed to be pointer-equal
    fn is_pointer_cons(&self) -> bool;
    /// Shallow-cons a term; if already consed, return `TermId`.
    ///
    /// Note that if a deep-cons property is desired, this function should
    /// only ever be called with deep-consed terms!
    fn shallow_cons(&mut self, id: &TermId) -> Option<TermId>;
    /// Try to cons a `Term`.
    fn try_cons(&self, id: &Term) -> Result<Option<TermId>, ()>;
    /// Check whether this `TermId` is consed
    fn check_cons(&self, id: &Term) -> bool;
    /// Get a term with the given code, if any has been registered into this context.
    /// May not be the only term with that code in the case of a hash collision.
    fn uncons(&self, code: Code) -> Option<TermId>;
    /// Convert this to a trait pointer
    ///
    /// Note: due to trait issues, there can be no default implementation for this
    fn as_dyn_cons_mut(&mut self) -> &mut dyn ConsCtx;
}

impl ConsCtx for () {
    #[inline]
    fn is_pointer_cons(&self) -> bool {
        false
    }

    #[inline]
    fn shallow_cons(&mut self, _id: &TermId) -> Option<TermId> {
        None
    }

    #[inline]
    fn try_cons(&self, _id: &Term) -> Result<Option<TermId>, ()> {
        Ok(None)
    }

    #[inline]
    fn check_cons(&self, _id: &Term) -> bool {
        true
    }

    #[inline]
    fn uncons(&self, _code: Code) -> Option<TermId> {
        None
    }

    #[inline]
    fn as_dyn_cons_mut(&mut self) -> &mut dyn ConsCtx {
        self
    }
}

impl<C: ConsCtx + ?Sized> ConsCtx for &mut C {
    #[inline]
    fn is_pointer_cons(&self) -> bool {
        (**self).is_pointer_cons()
    }

    #[inline]
    fn shallow_cons(&mut self, id: &TermId) -> Option<TermId> {
        (**self).shallow_cons(id)
    }

    #[inline]
    fn try_cons(&self, id: &Term) -> Result<Option<TermId>, ()> {
        (**self).try_cons(id)
    }

    #[inline]
    fn check_cons(&self, id: &Term) -> bool {
        (**self).check_cons(id)
    }

    #[inline]
    fn uncons(&self, code: Code) -> Option<TermId> {
        (**self).uncons(code)
    }

    #[inline]
    fn as_dyn_cons_mut(&mut self) -> &mut dyn ConsCtx {
        //TODO: think about this
        (**self).as_dyn_cons_mut()
    }
}